package drds.plus.sql_process.optimizer.cost_esitimater;

import drds.plus.sql_process.abstract_syntax_tree.expression.bind_value.BindValue;
import drds.plus.sql_process.abstract_syntax_tree.node.Node;
import drds.plus.sql_process.abstract_syntax_tree.node.query.MergeQuery;
import drds.plus.sql_process.abstract_syntax_tree.node.query.Query;

public class MergeNodeCostEstimater implements CostEstimater {

    public Cost estimate(Query query) {
        MergeQuery mergeQueryNode = (MergeQuery) query;
        Cost cost = new Cost();
        long keyFilteredCount = 0;
        long keyFilteredAndValueFilteredCount = 0;
        long diskIoCost = 0;
        long networkTransferCount = 0;
        //
        if (!(mergeQueryNode.getNodeList().get(0) instanceof Query)) {
            return cost;
        }
        for (Node subNode : mergeQueryNode.getNodeList()) {
            Cost subCost = CostEsitimaterFactory.estimate((Query) subNode);
            keyFilteredCount += subCost.getKeyFilteredCount();
            keyFilteredAndValueFilteredCount += subCost.getKeyFilteredAndValueFilteredCount();
            // 如果两个不在一个节点上，就会产生网络开销，需要把sub的数据传送到merge节点上
            if (mergeQueryNode.getDataNodeId() != null) {
                if (!mergeQueryNode.getDataNodeId().equals(subNode.getDataNodeId())) {
                    networkTransferCount += subCost.getKeyFilteredAndValueFilteredCount();
                }
            }
        }
        if (query.getLimitFrom() != null && query.getLimitTo() != null) {
            Object from = query.getLimitFrom();
            if (from instanceof BindValue) {
                from = ((BindValue) from).getValue();
            }
            Object to = query.getLimitTo();
            if (to instanceof BindValue) {
                to = ((BindValue) to).getValue();
            }
            if (from instanceof Long && to instanceof Long) {
                keyFilteredAndValueFilteredCount = ((Long) from - (Long) to);
            }
        }
        cost.setKeyFilteredCount(keyFilteredCount);
        cost.setKeyFilteredAndValueFilteredCount(keyFilteredAndValueFilteredCount);
        cost.setDiskIoCost(diskIoCost);
        cost.setDependentOnOtherQuery(true);
        cost.setNetworkTransferCount(networkTransferCount);
        return cost;
    }

}
